package com.lz.sports.ui

import android.animation.ObjectAnimator
import android.content.Context
import android.os.Bundle
import android.view.View
import android.widget.ImageView
import androidx.lifecycle.lifecycleScope
import com.github.mjdev.libaums.fs.UsbFile
import com.lz.comm.SP
import com.lz.comm.net.HttpManager
import com.lz.library.base.BaseActivity
import com.lz.library.extension.click
import com.lz.library.extension.resString
import com.lz.library.extension.showToast
import com.lz.library.utils.ActivityScrollObserver
import com.lz.sports.BR
import com.lz.sports.LogUtils
import com.lz.sports.R
import com.lz.sports.bean.ParcelableString
import com.lz.sports.core.K_IS_SUPER_MANAGER
import com.lz.sports.core.ProjectManager
import com.lz.sports.core.VerifyManager
import com.lz.sports.core.v_isSuperManager
import com.lz.sports.databinding.ActSysSettingBinding
import com.lz.sports.dialog.*
import com.lz.sports.service.UsbBroadcastReceiver
import com.lz.sports.utils.ToastUtils
import com.lz.sports.utils.UploadUtils
import com.lz.sports.vm.SysSettingViewModel
import com.lz.sports.widget.ExpandLinearLayout
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import java.io.File

//系统设置
class SysSettingActivity : BaseActivity<SysSettingViewModel, ActSysSettingBinding>(),
    WarningDialog.OnWarningConfirmListener,
    UsbFileDialog.OnItemClickListener, ParcelableSelectDialog.OnSelectedListener,
    EditPublicDialog.OnEditConfirmListener{

    companion object {
        //上传模式选择
        const val REQUEST_UPLOAD = 1

        //检录模式
        const val REQUEST_CHECK_IN = 2

        //签到方式
        const val REQUEST_SIGN_IN = 3

        //查询
        const val REQUEST_SCORE_QUERY = 4

        //成绩确认
        const val REQUEST_SCORE_SURE = 5

        //考区
        const val REQUEST_AREA = 6

        //考点
        const val REQUEST_SITE = 7
    }

    //USB权限和插拔广播
    private val usbReceiver by lazy { UsbReceiver(this) }

    //遍历列表与复制
    private var listFileJob: Job? = null

    //当前弹窗的文件选择
    private var usbFileDialog: UsbFileDialog? = null

    override fun getLayoutRes(): Int = R.layout.act_sys_setting

    override fun getVMVariableId(): Int = BR.vm

    override fun init() {
        usbReceiver.register()
    }

    override fun initObserve() {
        viewModel.zipAddress.observe(this) {
            val baseUrl = HttpManager.baseUrl
            if (it.address != null && baseUrl != null) {
                val url = "${baseUrl}${it.address}"
                LogUtils.i("download url = $url")
                val tmpFile = File(UploadUtils.tmpPath(), "${System.currentTimeMillis()}.tmp")
                val zipFile = File(UploadUtils.tmpPath(), "${System.currentTimeMillis()}.zip")
                val dialog = ZipDownloadDialog.show(this@SysSettingActivity, url, tmpFile.absolutePath, zipFile.absolutePath)
                dialog.downloadListener = object : ZipDownloadDialog.DownloadListener {
                    override fun onResult(dialog: ZipDownloadDialog, path: String) {
                        zipCopyDialog(zipFile)
                    }
                }
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        usbReceiver.unregisterReceiver()
    }

    override fun initData(savedState: Bundle?) {
        ActivityScrollObserver.observe(this, binding.root)
        lifecycleScope.launch {
            arrayOf(
                binding.llService,
                binding.llLocal,
                binding.llResult,
                binding.llPrinter,
                binding.llSound,
                binding.llOther,
                binding.tvSave
            ).click().collect { onClick(it) }
        }

        lifecycleScope.launch {
            arrayOf(
                binding.tvModel, binding.tvLine, binding.tvArea, binding.tvSite,
                binding.tvSign, binding.tvQuery, binding.tvSure, binding.tvFile,
                binding.tvDownload, binding.tvLog
            ).click().collect {
                when (it.id) {
                    R.id.tv_area -> {
                        val areaList = ProjectManager.examPlan?.examAreaList
                        if (areaList != null && areaList.isNotEmpty()) {
                            ParcelableSelectDialog.show(
                                this@SysSettingActivity,
                                R.string.select.resString(),
                                ProjectManager.currentExamArea,
                                areaList as ArrayList<out ParcelableString>,
                                REQUEST_AREA
                            )
                        }
                    }
                    R.id.tv_site -> {
                        val siteList = ProjectManager.currentExamArea?.examSiteList
                        if (siteList != null && siteList.isNotEmpty()) {
                            ParcelableSelectDialog.show(
                                this@SysSettingActivity,
                                R.string.select.resString(),
                                ProjectManager.currentExamSite,
                                siteList as ArrayList<out ParcelableString>,
                                REQUEST_SITE
                            )
                        }
                    }
                    R.id.tv_model -> ParcelableSelectDialog.show(
                        this@SysSettingActivity, R.string.select.resString(),
                        viewModel.uploadModel.value, viewModel.uploadModels, REQUEST_UPLOAD
                    )
                    R.id.tv_line -> ParcelableSelectDialog.show(
                        this@SysSettingActivity, R.string.select.resString(),
                        viewModel.inspectModel.value, VerifyManager.inspectModels(), REQUEST_CHECK_IN
                    )
                    R.id.tv_sign -> ParcelableSelectDialog.show(
                        this@SysSettingActivity, R.string.select.resString(),
                        viewModel.signInModel.value, VerifyManager.signInModels(), REQUEST_SIGN_IN
                    )
                    R.id.tv_query -> ParcelableSelectDialog.show(
                        this@SysSettingActivity, R.string.select.resString(),
                        viewModel.queryModel.value, VerifyManager.queryModels(), REQUEST_SCORE_QUERY
                    )
                    R.id.tv_sure -> ParcelableSelectDialog.show(
                        this@SysSettingActivity, R.string.select.resString(),
                        viewModel.sureModel.value, VerifyManager.sureModels(), REQUEST_SCORE_SURE
                    )
                    R.id.tv_file -> {
                        listFileJob = lifecycleScope.launch {
                            showLoading()
                            val job = async(Dispatchers.Default) {
                                usbReceiver.scanFileList()
                            }
                            val listFile = job.await()
                            if (listFile.isNotEmpty()) {
                                usbFileDialog = UsbFileDialog(this@SysSettingActivity, listFile)
                                usbFileDialog!!.onItemClickListener = this@SysSettingActivity
                                usbFileDialog!!.show()
                            }
                            hideLoading()
                        }
                    }
                    R.id.tv_download -> EditPublicDialog.show(
                        this@SysSettingActivity,
                        R.string.sys_plan_id.resString(), R.string.sys_download_id.resString()
                    )
                    R.id.tv_log -> viewModel.uploadLog()
                }
            }
        }
    }

    private fun onClick(v: View) {
        when (v.id) {
            R.id.ll_service -> animSelect(binding.ellService, binding.ivTag0)
            R.id.ll_local -> animSelect(binding.ellLocal, binding.ivTag1)
            R.id.ll_result -> animSelect(binding.ellResult, binding.ivTag2)
            R.id.ll_printer -> animSelect(binding.ellPrinter, binding.ivTag3)
            R.id.ll_sound -> animSelect(binding.ellSound, binding.ivTag4)
            R.id.ll_other -> animSelect(binding.ellOther, binding.ivTag5)
            R.id.tv_save -> {
                val isSuperManager = SP.getBoolean(K_IS_SUPER_MANAGER, v_isSuperManager)
                if (viewModel.isSuper.value != isSuperManager) {
                    WarningDialog.show(this@SysSettingActivity, R.string.sys_change_model.resString())
                } else {
                    viewModel.save()
                }
            }
        }
    }

    private fun animSelect(layout: ExpandLinearLayout, iv: ImageView) {
        layout.select()
        if (layout.isExpand) {
            ObjectAnimator.ofFloat(iv, "rotation", -90f, 0f)
        } else {
            ObjectAnimator.ofFloat(iv, "rotation", 0f, -90f)
        }.start()
    }

    override fun onConfirm(dialog: WarningDialog, requestCode: Int) {
        viewModel.save()
    }

    private inner class UsbReceiver(context: Context) : UsbBroadcastReceiver(context) {

        override fun onAttachedStorage() {
            R.string.sys_zip_in.showToast()
            cancelZip()
        }

        override fun onDetachedStorage() {
            R.string.sys_zip_out.showToast()
            cancelZip()
        }
    }

    override fun onItemClick(usbFile: UsbFile) {
        val dialog = UsbCopyDialog(this, usbFile, UploadUtils.examineeImportsPath())
        dialog.onCopiedListener = object : UsbCopyDialog.OnCopiedListener {
            override fun onCopied(isSuccess: Boolean) {
                viewModel.importsProjectOver(isSuccess)
                if (isSuccess) {
                    ToastUtils.showMyToast(R.string.sys_zip_success)
                } else {
                    ToastUtils.showMyToast(R.string.sys_zip_fail)
                }
            }
        }
        dialog.show()
        usbFileDialog?.dismiss()
    }

    private fun zipCopyDialog(zipFile: File) {
        val dialog = ZipCopyDialog(this, zipFile, UploadUtils.examineeImportsPath())
        dialog.onCopiedListener = object : ZipCopyDialog.OnCopiedListener {
            override fun onCopied(isSuccess: Boolean) {
                viewModel.importsProjectOver(isSuccess)
                if (isSuccess) {
                    ToastUtils.showMyToast(R.string.sys_zip_success)
                } else {
                    ToastUtils.showMyToast(R.string.sys_zip_fail)
                }
            }
        }
        dialog.show()
    }

    //关闭USB文件选择弹窗
    private fun cancelZip() {
        listFileJob?.cancel()
        usbFileDialog?.dismiss()
    }

    override fun onSelected(dialog: ParcelableSelectDialog, position: Int, requestCode: Int) {
        dialog.dismiss()
        when (requestCode) {
            REQUEST_AREA -> viewModel.selectExamArea(position)
            REQUEST_SITE -> viewModel.selectExamSite(position)
            REQUEST_UPLOAD -> viewModel.selectUploadModel(position)
            REQUEST_CHECK_IN -> viewModel.selectCheckInModel(position)
            REQUEST_SIGN_IN -> viewModel.selectSignInModel(position)
            REQUEST_SCORE_QUERY -> viewModel.selectScoreQueryModel(position)
            REQUEST_SCORE_SURE -> viewModel.selectScoreSureModel(position)
        }
    }

    override fun onEditConfirm(dialog: EditPublicDialog, text: String, requestCode: Int) {
        dialog.dismiss()
        viewModel.zipInfo(text)
    }
}